//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Windows.Media;
using OpenLS.Core.Serialization;

namespace OpenLS.Spreadsheet
{
#if DEBUG
    [ContractClass(typeof (FillContract))]
#endif
    public abstract class Fill: IOfficeXmlSerializable, INotifyPropertyChanged
    {

        /*public static implicit operator Brush(Fill f)
        {
            if (f == null)
                return null;
            return f.Brush;
        }
        public static implicit operator Fill(Brush b)
        {
            Fill result = GetFill(b);
            if (result == null)
            {
                ColorReference c = ColorReference.GetColorReference(b);
                if (c != null)
                {
                    PatternFill p = new PatternFill();
                    p.Type = PatternType.Solid;
                    p.ForegroundColor = c;
                    result = p;
                    SetFill(b, result);
                    return result;
                }
                if (b is SolidColorBrush)
                {
                    PatternFill p = new PatternFill();
                    p.Type = PatternType.Solid;
                    p.ForegroundColor = new RgbColorReference(((SolidColorBrush)b).Color);
                    result = p;
                    if (!b.IsFrozen)
                        SetFill(b, result);
                }
            }
            return result;
        }
         * */

        private int id;

        internal int Id
        {
            get { return id; }
            set { id = value; }
        }
        private PatternType type;

        public PatternType Type
        {
            get { return type; }
            protected set { type = value; }
        }
	
	
        
        public override abstract int GetHashCode();
        public override bool Equals(object obj)
        {
            Fill f = obj as Fill;
            if (f != null)
                return Equals(f);
            return false;
        }
        public abstract bool Equals(Fill fill);

        internal static Fill ReadFill(ReadContext context)
        {
            using (ReadContext c = context.Read("fill"))
            {
                c.AddData<FillMarker>(FillMarker.Instance);
                switch (c.ReaderLocalName)
                {
                    case "patternFill":
                        return c.ReadElement<PatternFill>(delegate { return new PatternFill(); });
                    case "gradientFill":
                        return c.ReadElement<GradientFill>(delegate { return new GradientFill(); });
                    case null: return new NullFill();
                    default: throw new NotSupportedException();
                }
            }
        }
        //\\const string xmlName = "fill";
        
        internal abstract Fill Clone();
#if DEBUG
        [ContractClassFor(typeof (Fill))]
        abstract class FillContract: Fill
        {
            internal override Fill Clone()
            {
                Contract.Ensures(Contract.Result<Fill>() != null);
                Contract.Ensures(Contract.Result<Fill>() != this);
                Contract.Ensures(Contract.Result<Fill>().Equals(this));
                Contract.Ensures(GetHashCode() == Contract.OldValue(GetHashCode()));
                throw new NotSupportedException();
            }
        }
#endif

        

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        internal void NotifyPropertyChanged(string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null);
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #region IOfficeXmlSerializable Members

        internal abstract void ReadXmlCore(ReadContext context);


        internal abstract void WriteXmlCore(WriteContext context);
       
        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            ReadXmlCore(context);
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            WriteXmlCore(context);
        }

        #endregion

        internal static Fill NewSolidFill(Color color)
        {
            var result = new PatternFill(color, color, PatternType.Solid);
                                     /*{
                                         BackgroundColor = color,
                                         ForegroundColor = color,
                                         Type = PatternType.Solid
                                     };*/
            return result;
        }
    }
}
